package jinyilw.swing.graphics;

import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;

public class ShapeTools
{
	private static Shape checkmark;

	private ShapeTools()
	{
	}

	public static Shape getCheckmark()
	{
		if (checkmark == null)
		{
			Path2D.Float path = new Path2D.Float();
			path.moveTo(3.8f, 7.5f);
			path.lineTo(5.9f, 10f);
			path.lineTo(10.55f, 3.5f);
			checkmark = path;
		}
		return checkmark;
	}

	/**
	 * 创建闭合路径
	 */
	public static Path2D createPath(double... points)
	{
		return createPath(true, points);
	}

	/**
	 * 创建路径
	 */
	public static Path2D createPath(boolean close, double... points)
	{
		Path2D path = new Path2D.Float();
		path.moveTo(points[0], points[1]);
		for (int i = 2; i < points.length; i += 2)
			path.lineTo(points[i], points[i + 1]);
		if (close)
			path.closePath();
		return path;
	}

	public static Shape createArrowShape(int direction, boolean close, float w,
			float h)
	{
		switch (direction)
		{
			//NORTH
			case 1:
				return createPath(close, 0, h, (w / 2f), 0, w, h);
			//EAST
			case 3:
				return createPath(close, 0, 0, w, (h / 2f), 0, h);
			//SOUTH
			case 5:
				return createPath(close, 0, 0, (w / 2f), h, w, 0);
			//WEST
			case 7:
				return createPath(close, w, 0, 0, (h / 2f), w, h);
			default:
				return new Path2D.Float();
		}
	}

	public static Shape createTriangle(int direction, float w, float h)
	{
		return createArrowShape(direction, true, w, h);
	}

	public static Path2D createRectangle(float x, float y, float width,
			float height, float lineWidth)
	{
		Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
		path.append(new Rectangle2D.Float(x, y, width, height), false);
		path.append(
				new Rectangle2D.Float(x + lineWidth, y + lineWidth,
						width - (lineWidth * 2), height - (lineWidth * 2)),
				false);
		return path;
	}

	public static Path2D createRoundRectangle(float x, float y, float width,
			float height, float lineWidth, float arcTopLeft, float arcTopRight,
			float arcBottomLeft, float arcBottomRight)
	{
		Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD);
		path.append(createRoundRectanglePath(x, y, width, height, arcTopLeft,
				arcTopRight, arcBottomLeft, arcBottomRight), false);
		path.append(
				createRoundRectanglePath(x + lineWidth, y + lineWidth,
						width - (lineWidth * 2), height - (lineWidth * 2),
						arcTopLeft - lineWidth, arcTopRight - lineWidth,
						arcBottomLeft - lineWidth, arcBottomRight - lineWidth),
				false);
		return path;
	}

	public static Shape createRoundRectanglePath(float x, float y, float width,
			float height, float arcTopLeft, float arcTopRight,
			float arcBottomLeft, float arcBottomRight)
	{
		if (arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0
				&& arcBottomRight <= 0)
			return new Rectangle2D.Float(x, y, width, height);

		// limit arcs to min(width,height)
		float maxArc = Math.min(width, height) / 2;
		arcTopLeft = (arcTopLeft > 0) ? Math.min(arcTopLeft, maxArc) : 0;
		arcTopRight = (arcTopRight > 0) ? Math.min(arcTopRight, maxArc) : 0;
		arcBottomLeft = (arcBottomLeft > 0)
				? Math.min(arcBottomLeft, maxArc)
				: 0;
		arcBottomRight = (arcBottomRight > 0)
				? Math.min(arcBottomRight, maxArc)
				: 0;

		float x2 = x + width;
		float y2 = y + height;

		// same constant as in java.awt.geom.EllipseIterator.CtrlVal used to
		// paint circles
		double c = 0.5522847498307933;
		double ci = 1. - c;
		double ciTopLeft = arcTopLeft * ci;
		double ciTopRight = arcTopRight * ci;
		double ciBottomLeft = arcBottomLeft * ci;
		double ciBottomRight = arcBottomRight * ci;

		Path2D rect = new Path2D.Float();
		rect.moveTo(x2 - arcTopRight, y);
		rect.curveTo(x2 - ciTopRight, y, x2, y + ciTopRight, x2,
				y + arcTopRight);
		rect.lineTo(x2, y2 - arcBottomRight);
		rect.curveTo(x2, y2 - ciBottomRight, x2 - ciBottomRight, y2,
				x2 - arcBottomRight, y2);
		rect.lineTo(x + arcBottomLeft, y2);
		rect.curveTo(x + ciBottomLeft, y2, x, y2 - ciBottomLeft, x,
				y2 - arcBottomLeft);
		rect.lineTo(x, y + arcTopLeft);
		rect.curveTo(x, y + ciTopLeft, x + ciTopLeft, y, x + arcTopLeft, y);
		rect.closePath();
		return rect;
	}

	public static Area createIntersectArea(Shape shape1, Shape shape2)
	{
		Area intersectArea = new Area(shape1);
		intersectArea.intersect(new Area(shape2));
		return intersectArea;
	}
}
